/* 
 * File:   simpleBash.c
 * Author: nico
 *
 * Created on 5. Juni 2012, 17:06
 */

#include <dirent.h> //para el la func cmd_ls
#define BUF 128
#define FIELD_MAX 10 
char mensaje[BUF];

int simpleBash_telnet(int *sockfd)
{
    int ret;
    do
    {
        ret=acceptAndParse(sockfd);
        
    }while(ret!=-1);
}

int acceptAndParse(int *sockfd)
{
    char cmd[BUF];
    char* cmdv[FIELD_MAX];
    int i,proof,cant, numbytes;
	
	strcpy(mensaje, "\n$ ");
	if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        	syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
    //Lee de la entrada
    //fgets(cmd, BUF, stdin);  
	memset(cmd, '\0', BUF);
	if ((numbytes=recv(*sockfd, cmd, BUF, 0)) == -1) {
		syslog(LOG_ERR, "%s%s\n", "recv: ",strerror(errno));
		return -1;
    }
	cmd[numbytes - 2] = '\0';
    //Verifica si todo el comando entro en el string cmd de longitud=BUF
    proof=0;
    for(i=0; i<100; i++)
        if(cmd[i]=='\n')
            proof=1;
    if(proof==0){
		sprintf(mensaje,"Error: El comando tiene mas que %d caracters", BUF);
		if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        	syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
        
	}
    
    //Separa las palabras del comando y las pone una palabra por vez en un vector
    //Despues de la 'ultima palabra guardamos un NULL
    int j=0;
    cmdv[j]=strtok(cmd," \n");
    do
	{
        if(j>=FIELD_MAX)
		{
            sprintf(mensaje, "Advertencia: No se procesan más que %d palabras!", FIELD_MAX);
			if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        		syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
		}
        j++;
        cmdv[j]=strtok(NULL," \n");
        
    }while(cmdv[j]!=NULL);
    cant=j;
    //cambiar despues*******************
    for(i=0;i<BUF;i++)
    {
        if(cmdv[j-1][i]=='\n')
        {
            cmdv[j-1][i]='\0';
            break;
        }
    }
    syslog(LOG_INFO, "%s\n", cmdv[0]);
    //Ver y controlar cual comando es y ejecutarlo
    if(strcmp(cmdv[0],"ls")==0)
    {
        cmd_ls(cmdv,cant, sockfd);
    }
    else if(strcmp(cmdv[0],"cd")==0)
    {
        cmd_cd(cmdv,cant, sockfd);
    }
    else if(strcmp(cmdv[0],"pwd")==0)
    {
        cmd_pwd(sockfd);
    }
    else if(strcmp(cmdv[0],"view")==0)
    {
        cmd_view(cmdv,cant, sockfd);
    }
    else if(strcmp(cmdv[0],"copy")==0)
    {
        cmd_copy(cmdv,cant, sockfd);
        
    }
    else if(strcmp(cmdv[0],"move")==0)
    {
        cmd_move(cmdv,cant, sockfd);
    }
    else if(strcmp(cmdv[0],"delete")==0)
    {
        cmd_delete(cmdv,cant, sockfd);
    }
    else if(strcmp(cmdv[0],"mkdir")==0)
    {
        cmd_mkdir(cmdv,cant, sockfd);
    }
    else if(strcmp(cmdv[0],"rmdir")==0)
    {
        cmd_rmdir(cmdv,cant, sockfd);
    }
    else if(strcmp(cmdv[0],"close")==0)
    {
        return -1;
    }
    else if(strcmp(cmdv[0],"help")==0)
    {
        cmd_help(sockfd);
    }
    else
    {
        strcpy(mensaje, "Comando no existe\n");
		if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        		syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
    }
    
    return 0;
}

int cmd_cd(char** cmdv,int cant, int *sockfd)
{
    char* path;
    
    if(cant > 1)
    {
        path=cmdv[1];
    }
    else if((path = getenv("HOME")) == NULL)  //CAMBIAR ??? *************************
    {
        path=".";
    }
    
    if(chdir(path) == -1)
    {
        sprintf(mensaje,"Error: cd\n%s\n",strerror(errno));
		if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        		syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
        return -1;
    }
    return 0;
}

int cmd_pwd(int *sockfd)
{
    char path[BUF];
    
    if(getcwd(path,BUF)==NULL)
    {
        sprintf(mensaje,"Error: pwd\n");
		if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        		syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
        return -1;
    }
    strcat(path, "\n");
	if (send(*sockfd, path, strlen(path), 0) == -1)
        		syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
    return 0;
}

int cmd_ls(char** cmdv,int cant, int *sockfd)
{
    char *path;
    DIR *dirp;
    struct dirent *entrada;
    int ppos=1;   //posicion del path
    int opc_a=0;  //Esta el argumento "-a"?
    int i;
    
    //Controlar si esta el arg. "-a" y
    //si esta, avanzar la posicion donde estaria el path, si hace falta
    for(i=0;i<cant;i++)
    {
        if(strcmp(cmdv[i],"-a")==0)
        {
            opc_a=1;
            if(i==ppos)
            {
                ppos++;
            }
        }
    }
    
    //Ver si se especifico un path para ls,
    //si no, poner el directoria actual como path
    if(cant>ppos)
    {
        path=cmdv[ppos];
    }
    else
    {
        path=".";
    }
    
    //Abrir un stream al directorio
    if((dirp = opendir(path)) == NULL)
    {
        sprintf(mensaje,"Error: opendir: %s",strerror(errno));
		if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        		syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
        return -1;
    }
    
    //Leer archivo por archivo en el directorio
    while((entrada = readdir(dirp)) != NULL)
    {
        if(opc_a==1)
        {
			strcpy(mensaje, entrada->d_name);
			strcat(mensaje, "\n");
			if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        		syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
        }
        else
        {
            //Filtrar los archivos ocultos
            if(entrada->d_name[0] != '.')
            {
                strcpy(mensaje, entrada->d_name);
				strcat(mensaje, "\n");
				if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        			syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
            }
        }
    }
    
    //Cerrar el stream al directorio
    closedir(dirp);
}

int cmd_view(char** cmdv,int cant, int *sockfd)
{
    char ch[BUF];
    FILE *fp;
    
    if(cant < 2)
    {
        sprintf(mensaje,"No hay suficientes argumentos! Ponga view <archivo>\n");
		if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        	syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
        return -1;
    }
    
    if((fp = fopen(cmdv[1],"r")) == NULL)
    {
        sprintf(mensaje,"Error al abrir archivo! %s\n",strerror(errno));
		if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        	syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
        return -1;
    }

    //Que BUF sea lo suficiente pequenho para que funcione bien con los sockets y send()
    while(fgets(ch,BUF,fp) != NULL)
    {
		if (send(*sockfd, ch, strlen(ch), 0) == -1)
        		syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
    }
    
    fclose(fp);
    return 0;
}

int cmd_copy(char** cmdv,int cant, int *sockfd)
{
    char cmd[BUF];
    
    if(cant<3)
    {
        sprintf(mensaje,"Error: Faltan parametros.. Se usa asi: copy <fuente> <destino>");
		if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        		syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
        return -1;
    }
    
    char *src = cmdv[1];
    char *dest = cmdv[2];
    
    sprintf( cmd, "cp -p -r \'%s\' \'%s\'", src, dest);
    
    if(system(cmd) != 0)
    {
        sprintf(mensaje,"Error: system()\n");
		if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        		syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
        return -1;
    }
    return 0;
}

int cmd_move(char** cmdv,int cant, int *sockfd)
{
    int i;
    int ult;
    char path[BUF];
    
    if(cant<3)
    {
        strcpy(mensaje, "Error: Faltan parametros.. ver help");
		if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        		syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
        return -1;
    }
    

    for(i=0; (cmdv[1][i]!='\0'); i++)
    {
        if(cmdv[1][i] == '/')
        {
            ult = i+1;
        }
    }

    strcpy(path,cmdv[2]);
    strcat(path,"/");
    strcat(path,(cmdv[1]+ult));

    if(rename(cmdv[1],path) == -1)
    {
        sprintf(mensaje,"Error: move .. %d %s\n",errno,strerror(errno));
                        if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
                        syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
        return -1;
    }
            
    return 0;
}

int cmd_delete(char** cmdv,int cant, int *sockfd)
{
    if(cant < 2)
    {
        sprintf(mensaje,"Error: Faltan parametros.. Se usa asi: delete <archivo>");
		if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        		syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
        return -1;
    }
    
    if(unlink(cmdv[1]) == -1)
    {
        sprintf(mensaje,"Error: delete .. %d %s\n",errno,strerror(errno));
		if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        		syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
        return -1;
    }
    return 0;
}

int cmd_mkdir(char** cmdv,int cant, int *sockfd)
{
    if(cant < 2)
    {
        sprintf(mensaje,"Error: Faltan parametros.. Se usa asi: mkdir <archivo>");
		if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        		syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
        return -1;
    }
    
    if(mkdir(cmdv[1],0755) == -1)
    {
        sprintf(mensaje,"Error: mkdir .. %d %s\n",errno,strerror(errno));
		if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        		syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
        return -1;
    }
    return 0;
}

int cmd_rmdir(char** cmdv,int cant, int *sockfd)
{
    if(cant < 2)
    {
        sprintf(mensaje, "Error: Faltan parametros.. Se usa asi: rmdir <archivo>");
		if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        		syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
        return -1;
    }
    
    if(rmdir(cmdv[1]) == -1)
    {
        sprintf(mensaje,"Error: rmdir .. %d %s\n",errno,strerror(errno));
		if (send(*sockfd, mensaje, strlen(mensaje), 0) == -1)
        		syslog(LOG_ERR, "%s%s\n", "send: ",strerror(errno));
        return -1;
    }
    return 0;
}

int cmd_help(int *sockfd)
{
    enviar("Pagina de ayuda para FTPLike\n\n",sockfd);
    enviar("Para su uso existen los sigientes comandos:\n\n",sockfd);
    enviar("  pwd:           Muestra la ruta completa del directorio actual\n\n",sockfd);
    enviar("  ls <path>:     Lista los archivos y directorios del contexto actual\n",sockfd);
    enviar("                 El parametro <path> es opcional.\n",sockfd);
    enviar("                 Ademas dispone de un parametro '-a' \n");
    enviar("                 para visualizar los archivos ocultos\n\n",sockfd);
    enviar("  cd <path>:     Cambia el directorio actual en el server\n",sockfd);
    enviar("                 <path> representa la ruta al directorio al que desea cambiar\n\n",sockfd);
    enviar("  view <path>:   Visualiza el contenido de un archivo\n",sockfd);
    enviar("                 <path> representa la ruta y el nombre del archivo\n\n",sockfd);
    enviar("  delete <path>: Recibe como parametro a <path> y lo borra\n\n",sockfd);
    enviar("  mkdir <path>:  Recibe mediante <path> un nombre de directorio y lo crea\n\n",sockfd);
    enviar("  rmdir <path>:  Recibe mediante <path> un nombre de directorio y lo borra\n\n",sockfd);
    enviar("  copy <fuente> <dest>: Copia un archivo a una dirección especifica\n",sockfd);
    enviar("                        <fuente> representa el archivo o directorio original\n",sockfd);
    enviar("                        <dest> representa el directorio hacia donde copiar\n\n",sockfd);
    enviar("  move <fuente> <dest>: Mueve un archivo a una dirección especifica\n",sockfd);
    enviar("                        <fuente> y <dest> se manejan y igual que en copy\n\n",sockfd);
    enviar("  close:         Cierra la conexión con el server\n\n",sockfd);
    enviar("  help:          Muestra esta ayuda\n\n",sockfd);
}

